<?php

class P2X2P {
	
	public $debug = false;
	public $DOM = false;
	
	public function __construct() {
		$this->DOM = new DOMDocument();
	}
	
	public function encode($var) {
		
		$value = $this->DOM->createElement('value');
		
		if(!is_array($var)) {
			$value_child = $this->DOM->createElement($this->encode_type($var));
			$value_child->appendChild($this->DOM->createTextNode($this->encode_value($var)));
			$value->appendChild($value_child);
		} else {
			$value->appendChild($this->encode_struct($var));
		}
		
		return $value;
	}
	
	public function error($errorNumber) {
		return Config::get("P2X2P",$errorNumber);
	}
	
	public function resetDOM() {
		$children = $this->DOM->childNodes;
		
		for($i=0; $i<$children->length; $i++) {
			$this->DOM->removeChild($this->DOM->firstChild);
		}
	}
	
	public function encode_struct($var) {
		
		$struct = $this->DOM->createElement('struct');
		
		foreach($var as $key=>$val) {
			$member = $this->DOM->createElement('member');	
			$name = $this->DOM->createElement('name');
			$name->appendChild($this->DOM->createTextNode($key));
			$member->appendChild($name);
			$member->appendChild($this->encode($val));
			$struct->appendChild($member);
		}
		
		return $struct;
	}
	
	public function encode_value($var) {
		
		switch($type=gettype($var)) {
			case 'string':
			case 'NULL':
				break;
				
			case 'boolean':
				$var=$var?1:0;
				break;
				
			case 'float':
			case 'double':
				break;
				
			case 'integer':
				break;
				
			case 'object':
				$var=base64_encode(gzcompress(serialize($var)));
				break;
				
			case 'array':
				return $this->encode_struct($var);
				break;
				
			default:
				Error::handler(null, 'Invalid Type - ' . $type, __FILE__, __LINE__);
				return false;
				break;
		}

		return $var;
	}
	
	public function encode_type($var) {
		
		switch($type=gettype($var)) {
			
			case 'string':
			case 'NULL':
				$return = 'string';
				break;
				
			case 'boolean':
				$return = 'boolean';
				break;
				
			case 'float':
			case 'double':
				$return = 'double';
				break;
				
			case 'integer':
				$return = 'int';
				break;
				
			case 'object':
				$return = 'Base64';
				break;
				
			case 'array':
				$return = 'array';
				break;
				
			default:
				Error::handler(null, 'Invalid Type - ' . $type, __FILE__, __LINE__);
				break;
		}
		
		return $return;
	}
	
	public function decode($node) {
		$value_kid = $node->firstChild;
		$type = $value_kid->nodeName;

		switch($type) {
			case 'string': 
			case 'NULL': 
				return (string) $value_kid->nodeValue; 
				break;
				
			case 'boolean':
				return (boolean) $value_kid->nodeValue; 
				break;
				
			case 'double':
				return (float) $value_kid->nodeValue;
				break;
				
			case 'int':
			case 'i4':
				return (int) $value_kid->nodeValue;
				break;
				
			case 'Base64':
				return unserialize(gzuncompress(base64_decode($value_kid->nodeValue)));
				break;
				
			case 'struct':
				return $this->decode_struct($value_kid);
				break;
				
			default:
				Error::handler(null, 'Invalid Type - ' . $type, __FILE__, __LINE__);
				return false;
				break;
		}
	}

	public function decode_struct($node) {
		$return = array();
		$members = $node->childNodes;

		for($i=0; $i<$members->length; $i++) {
			$name = $members->item($i)->getElementsByTagName('name')->item(0)->nodeValue;
			$value = $this->decode($members->item($i)->getElementsByTagName('value')->item(0));
			$return[$name?$name:0] = $value;
		}

		return $return;
	}
	
	
}